/**
 * userService.js - 用户服务
 * 
 * 这个模块提供与用户相关的业务逻辑，如获取用户列表、获取单个用户、创建用户、更新用户和删除用户。
 * 它作为控制器和数据模型之间的中间层，处理业务规则和数据转换。
 */

const { User } = require('../models/userModel');
const { ApiError } = require('../utils/errors');
const { Op } = require('sequelize');

/**
 * 用户服务类
 * 
 * 提供用户相关的业务逻辑方法
 */
class UserService {
  /**
   * 获取所有用户
   * 
   * 获取分页的用户列表
   * @param {Object} options - 分页和过滤选项
   * @param {number} options.page - 页码
   * @param {number} options.limit - 每页项目数
   * @param {string} options.search - 搜索关键字（可选）
   * @returns {Promise<Object>} - 包含用户列表和分页信息的对象
   */
  async getAllUsers({ page = 1, limit = 10, search = '' }) {
    try {
      // 构建查询条件
      const whereCondition = {};
      if (search) {
        whereCondition[Op.or] = [
          { username: { [Op.like]: `%${search}%` } },
          { email: { [Op.like]: `%${search}%` } },
        ];
      }

      // 计算偏移量
      const offset = (page - 1) * limit;

      // 查询用户并计算总数
      const { count, rows } = await User.findAndCountAll({
        where: whereCondition,
        limit,
        offset,
        attributes: { exclude: ['password', 'refreshToken'] }, // 排除敏感字段
        order: [['createdAt', 'DESC']], // 按创建时间降序排序
      });

      // 计算总页数
      const totalPages = Math.ceil(count / limit);

      // 返回用户列表和分页信息
      return {
        users: rows,
        pagination: {
          page: parseInt(page, 10),
          limit: parseInt(limit, 10),
          total: count,
          totalPages,
          hasNext: page < totalPages,
          hasPrev: page > 1,
        },
      };
    } catch (error) {
      throw new ApiError(500, '获取用户列表失败', error);
    }
  }

  /**
   * 获取单个用户
   * 
   * 通过ID获取用户信息
   * @param {string} id - 用户ID
   * @returns {Promise<Object>} - 用户对象
   * @throws {ApiError} - 如果用户不存在
   */
  async getUserById(id) {
    try {
      const user = await User.findByPk(id, {
        attributes: { exclude: ['password', 'refreshToken'] }, // 排除敏感字段
      });

      if (!user) {
        throw new ApiError(404, `ID为${id}的用户不存在`);
      }

      return user;
    } catch (error) {
      if (error instanceof ApiError) {
        throw error;
      }
      throw new ApiError(500, '获取用户信息失败', error);
    }
  }

  /**
   * 通过电子邮件获取用户
   * 
   * 用于身份验证流程
   * @param {string} email - 用户电子邮件
   * @returns {Promise<Object>} - 用户对象（包括密码）
   * @throws {ApiError} - 如果用户不存在
   */
  async getUserByEmail(email) {
    try {
      const user = await User.findOne({
        where: { email },
      });

      if (!user) {
        throw new ApiError(404, `电子邮件为${email}的用户不存在`);
      }

      return user;
    } catch (error) {
      if (error instanceof ApiError) {
        throw error;
      }
      throw new ApiError(500, '获取用户信息失败', error);
    }
  }

  /**
   * 创建用户
   * 
   * 创建新用户并返回用户信息（不包括密码）
   * @param {Object} userData - 用户数据
   * @returns {Promise<Object>} - 新创建的用户对象
   * @throws {ApiError} - 如果创建失败
   */
  async createUser(userData) {
    try {
      // 检查用户名是否已存在
      const existingUsername = await User.findOne({
        where: { username: userData.username },
      });
      if (existingUsername) {
        throw new ApiError(409, '用户名已被使用');
      }

      // 检查电子邮件是否已存在
      const existingEmail = await User.findOne({
        where: { email: userData.email },
      });
      if (existingEmail) {
        throw new ApiError(409, '电子邮件已被注册');
      }

      // 创建新用户
      const newUser = await User.create(userData);

      // 返回用户信息（不包括密码）
      const userWithoutPassword = await this.getUserById(newUser.id);
      return userWithoutPassword;
    } catch (error) {
      if (error instanceof ApiError) {
        throw error;
      }
      throw new ApiError(500, '创建用户失败', error);
    }
  }

  /**
   * 更新用户
   * 
   * 更新用户信息并返回更新后的用户
   * @param {string} id - 用户ID
   * @param {Object} updateData - 要更新的数据
   * @returns {Promise<Object>} - 更新后的用户对象
   * @throws {ApiError} - 如果用户不存在或更新失败
   */
  async updateUser(id, updateData) {
    try {
      // 检查用户是否存在
      const user = await User.findByPk(id);
      if (!user) {
        throw new ApiError(404, `ID为${id}的用户不存在`);
      }

      // 如果要更新用户名，检查是否已被使用
      if (updateData.username && updateData.username !== user.username) {
        const existingUsername = await User.findOne({
          where: { username: updateData.username },
        });
        if (existingUsername) {
          throw new ApiError(409, '用户名已被使用');
        }
      }

      // 如果要更新电子邮件，检查是否已被注册
      if (updateData.email && updateData.email !== user.email) {
        const existingEmail = await User.findOne({
          where: { email: updateData.email },
        });
        if (existingEmail) {
          throw new ApiError(409, '电子邮件已被注册');
        }
      }

      // 更新用户
      await user.update(updateData);

      // 返回更新后的用户信息（不包括密码）
      const updatedUser = await this.getUserById(id);
      return updatedUser;
    } catch (error) {
      if (error instanceof ApiError) {
        throw error;
      }
      throw new ApiError(500, '更新用户失败', error);
    }
  }

  /**
   * 删除用户
   * 
   * 通过ID删除用户
   * @param {string} id - 用户ID
   * @returns {Promise<boolean>} - 如果删除成功则返回true
   * @throws {ApiError} - 如果用户不存在或删除失败
   */
  async deleteUser(id) {
    try {
      // 检查用户是否存在
      const user = await User.findByPk(id);
      if (!user) {
        throw new ApiError(404, `ID为${id}的用户不存在`);
      }

      // 删除用户
      await user.destroy();
      return true;
    } catch (error) {
      if (error instanceof ApiError) {
        throw error;
      }
      throw new ApiError(500, '删除用户失败', error);
    }
  }

  /**
   * 更新用户的刷新令牌
   * 
   * @param {string} userId - 用户ID
   * @param {string} refreshToken - 新的刷新令牌
   * @returns {Promise<boolean>} - 如果更新成功则返回true
   */
  async updateRefreshToken(userId, refreshToken) {
    try {
      await User.update(
        { refreshToken },
        { where: { id: userId } }
      );
      return true;
    } catch (error) {
      throw new ApiError(500, '更新刷新令牌失败', error);
    }
  }

  /**
   * 通过刷新令牌查找用户
   * 
   * @param {string} refreshToken - 刷新令牌
   * @returns {Promise<Object>} - 用户对象
   * @throws {ApiError} - 如果找不到用户
   */
  async findUserByRefreshToken(refreshToken) {
    try {
      const user = await User.findOne({
        where: { refreshToken },
        attributes: { exclude: ['password'] },
      });

      if (!user) {
        throw new ApiError(404, '无效的刷新令牌');
      }

      return user;
    } catch (error) {
      if (error instanceof ApiError) {
        throw error;
      }
      throw new ApiError(500, '查找用户失败', error);
    }
  }

  /**
   * 清除用户的刷新令牌
   * 
   * 用于用户登出
   * @param {string} userId - 用户ID
   * @returns {Promise<boolean>} - 如果清除成功则返回true
   */
  async clearRefreshToken(userId) {
    try {
      await User.update(
        { refreshToken: null },
        { where: { id: userId } }
      );
      return true;
    } catch (error) {
      throw new ApiError(500, '清除刷新令牌失败', error);
    }
  }

  /**
   * 更新用户的最后登录时间
   * 
   * @param {string} userId - 用户ID
   * @returns {Promise<boolean>} - 如果更新成功则返回true
   */
  async updateLastLogin(userId) {
    try {
      await User.update(
        { lastLogin: new Date() },
        { where: { id: userId } }
      );
      return true;
    } catch (error) {
      throw new ApiError(500, '更新最后登录时间失败', error);
    }
  }
}

module.exports = new UserService();